<?php
class SecurityUtils
{
	private $strEncrypt;		//----- password key
	private $intValidateNum;	//----- check code 
		
	function __construct()
	{		
		while(($this->intValidateNum = rand() % 10000) < 1000); 
		
		$this->strEncrypt='LingDeming20050519'.date('YmdH');
	}
	
	public function iGetCheckCode()
	{
		return $this->intValidateNum;
	}
	
	/* decrypt 和 encrypt 的中间方法
	 *
	 * @param  return int       ← 返回随机数											
	 */
	private function keyED($txt,$encrypt_key)	//-----decrypt and encrypt 使用的中间函数
	{ 
		$encrypt_key = md5($encrypt_key); 
		$ctr=0; 
		$tmp = ""; 
		for ($i=0;$i<strlen($txt);$i++){ 
			if ($ctr==strlen($encrypt_key)) $ctr=0; 
			$tmp.= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1); 
			$ctr++; 
		} 
		return $tmp; 
	} 

	/* 数据加密(默认用来进行验证码登陆使用）
	 *
	 * @param  string txt   		← 要加密的数据											
	 * @param  string key   		← 加密的密匙											
	 * @param  return string       	← 返回加密后的字串											
	 */
	public function encrypt($txt='',$key='')
	{ 
		if(empty($key))
			$key=$this->strEncrypt;
		if(empty($txt))
			$txt=$this->intValidateNum;
		srand((double)microtime()*1000000); 
		$encrypt_key = md5(rand(0,32000)); 
		$ctr=0; 
		$tmp = ""; 
		for ($i=0;$i<strlen($txt);$i++){ 
			if ($ctr==strlen($encrypt_key)) $ctr=0; 
			$tmp.= substr($encrypt_key,$ctr,1) .(substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1)); 
			$ctr++; 
		} 
		return urlencode($this->keyED($tmp,$key)); 
	}
		
	/* 数据解密(默认用来进行验证码登陆使用）
	 *
	 * @param  string txt   		← 要解密的数据											
	 * @param  string key   		← 解密的密匙											
	 * @param  return string       	← 返回解密后的字串，解密的数据为空时返回值为空											
	 */
	public function decrypt($txt='',$key='')
	{ 
		if(empty($key))
			$key=$this->strEncrypt;
		$txt=urldecode($txt);
		$txt = $this->keyED($txt,$key); 
		$tmp = ""; 
		for ($i=0;$i<strlen($txt);$i++){ 
			$md5 = substr($txt,$i,1); 
			$i++; 
			$tmp.= (substr($txt,$i,1) ^ $md5); 
		} 
		return $tmp; 
	}

	/* funEncode 和 funDecode 的中间方法
	 *
	 * @param  return int       ← 返回随机数											
	 */
	public function make_seed() { 
    	list($usec, $sec) = explode(' ', microtime()); 
    	return(float) $sec +((float) $usec * 100000); 
	} 

	/* 数据加密---->要mcrypt库支持
	 *
	 * @param  string data   		← 要加密的数据											
	 * @param  string key   		← 加密的密匙											
	 * @param  string arithmetic  	← 加密用的算法，默认为( Twofish 算法， ECB 模式 ,MCRYPT_RIJNDAEL_128算法存在暗匙，可以给每个数据分一个密匙）										
	 * @param  return str OR arr	← 返回加密后的字串，加密的数据为空时返回值为空,MCRYPT_RIJNDAEL_128算法返回的是数组											
	 */
	public function funEncode($data, $key,$arithmetic='Twofish') 
	{ 
    	if(empty($data))
    		return '';	//----- 加密的数据为空，返回值为空
	    else{
		    if($arithmetic == 'MCRYPT_RIJNDAEL_128'){
			    $arrData=array();
			    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_RAND); 
				$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$data, MCRYPT_MODE_CBC, $iv); 
	    		
	    		$arrData['iv'] = $iv;				//-----	加密的暗匙（解密时用)
	    		$arrData['encrypted'] = $encrypted;	//----- 加密后的字符串
				return $arrData;
			}else{
			    srand($this->make_seed());    
			    $td = mcrypt_module_open('twofish', '', 'ecb', ''); //----- Twofish 算法， ECB 模式
			    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND); //----- If u use MCRYPT_RAND, make sure to invoke strand() first.
			    $ks = mcrypt_enc_get_key_size($td); 
			    $gen_key = substr(md5($key), 0, $ks); 
			    mcrypt_generic_init($td, $gen_key, $iv); 
			    $encrypted = mcrypt_generic($td, $data); 
			    mcrypt_module_close($td); 
			    return $encrypted;
		   }
	   }
	} 

	/* 数据解密---->要mcrypt库支持
	 *
	 * @param  string data   		← 要解密的数据											
	 * @param  string key   		← 解密的密匙											
	 * @param  string arithmetic  	← 解密用的算法,默认为( Twofish 算法， ECB 模式 )						
	 * @param  return string       	← 返回解密后的字串，解密的数据为空时返回值为空											
	 */
	public function funDecode($data, $key, $arithmetic='Twofish') 
	{ 
	    if(!is_array($data))
	    	if(empty($data))
	    		return '';	//----- 解密的数据为空，返回值为空
	    if(is_array($data))
	    	if(empty($data['encrypted']))
	    		return '';	//----- 解密的数据为空，返回值为空
	    
	    if($arithmetic == 'MCRYPT_RIJNDAEL_128'){
    		$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data['encrypted'], MCRYPT_MODE_CBC, $data['iv']); 
    		return $decrypted;
		}else{	    
		    srand($this->make_seed());
		    $td = mcrypt_module_open('twofish', '', 'ecb', '');  //----- Twofish algorithm, ECB Mode
		    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND); 
		    $ks = mcrypt_enc_get_key_size($td); 
		    $gen_key = substr(md5($key), 0, $ks); 
		    mcrypt_generic_init($td, $gen_key, $iv); 
		    $decrypted = mdecrypt_generic($td, $data); 
		    mcrypt_generic_deinit($td); 	//----- Clear all buffer needed by the encryption
		    mcrypt_module_close($td); 	 	//----- Close the module
		    return trim($decrypted); 
		}
	} 

	/* 数据加密应用
	 *
	 * @param  string 	data   		← 要加密的数据											
	 * @param  string 	key   		← 加密的密匙											
	 * @param  int	  	level  		← 1：普通，2：中级，3：高级（默认）	级别越低速度更快									
	 * @param  boolean 	isEncode	← 是否对数据进行加密，默认为加密，为false时数据不加密										
	 * @param  return 	str OR arr	← 返回加密后的字串，加密的数据为空时返回值为空,加密失败后返回数组和错误信息										
	 */
	public function funEncoding($data, $key,$level=3,$isEncode = true) 
	{ 
  		if(empty($data) OR !($isEncode))
    		return $data;	//----- 加密的数据为空，返回值为空,或选择不对数据加密
		$arrBack=array();
		if($level == 3){
			if(function_exists('mcrypt_encrypt'))	//--- 要mcrypt库支持
				return $this->funEncode($data, $key);
			else{	//--- 加密失败后返回数组和错误信息
				$this->errorInfo = 'PHP环境不支持mcrypt库';
				$arrBack['data'] = $data;
				$arrBack['errorInfo']  = 'PHP not abet mcrypt library';
				$arrBack['errorLevel'] = 3;	//--- 错误级别为系统环境错误
				return $arrBack;
			}
		}else{	//--- 加密失败后返回数组和错误信息
			$this->errorInfo = '没有找到相应的安全等级';
			$arrBack['data'] = $data;
			$arrBack['errorInfo']  = 'It not find secure level';
			$arrBack['errorLevel'] = 1;//--- 其他错误 （警告级别）
			return $arrBack;
		}
  	}
  	
	/* 数据解密应用
	 *
	 * @param  string 	data   		← 要解密的数据											
	 * @param  string 	key   		← 解密的密匙											
	 * @param  int	  	level  		← 1：普通，2：中级，3：高级（默认）	级别越低速度更快									
	 * @param  boolean 	isEncode	← 是否对数据进行解密，默认为解密，为false时数据不解密										
	 * @param  return 	str OR arr	← 返回解密后的字串，解密的数据为空时返回值为空,解密失败后返回数组和错误信息											
	 */
	public function funDecoding($data, $key,$level=3,$isDecode = true) 
	{ 
  		if(empty($data) OR !($isDecode))
    		return $data;	//----- 解密的数据为空，返回值为空,或选择不对数据解密
		$arrBack=array();

		if($level == 3){
			if(function_exists('mcrypt_encrypt')){	//--- 要mcrypt库支持
				return $this->funDecode($data, $key);
			}else{	//--- 解密失败后返回数组和错误信息
				$this->errorInfo = 'PHP环境不支持mcrypt库';
				$arrBack['data'] = $data;
				$arrBack['errorInfo']  = 'PHP not abet mcrypt library';
				$arrBack['errorLevel'] = 3;	//--- 错误级别为系统环境错误
				return $arrBack;
			}
		}else{	//--- 解密失败后返回数组和错误信息
			$this->errorInfo = '没有找到相应的安全等级';
			$arrBack['data'] = $data;
			$arrBack['errorInfo']  = 'It not find secure level';
			$arrBack['errorLevel'] = 1;//--- 其他错误 （警告级别）
			return $arrBack;
		}
  	} 
}
?>